package org.fitweb.files;

import org.apache.commons.io.filefilter.IOFileFilter;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static java.text.MessageFormat.*;
import static org.apache.commons.io.FileUtils.*;
import static org.fitweb.files.PathFinder.*;

public class DirectoryScrounger implements FileCopier {

    static final String MISSING_DIRECTORY_ERROR = "Directory does not exist: {0}";

    private FileCopier copier;

    public DirectoryScrounger() {
        this.copier = this;
    }

    DirectoryScrounger(FileCopier copier) {
        this.copier = copier;
    }

    public List<File> locateTests(File testInputDirectory) throws IOException {
        if (!testInputDirectory.exists()) {
            throw new IllegalArgumentException(format(MISSING_DIRECTORY_ERROR, testInputDirectory));
        }
        return findTestsIn(testInputDirectory);
    }

    private List<File> findTestsIn(File node) throws IOException {
        ArrayList<File> tests = new ArrayList<File>();
        File[] files = node.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                tests.addAll(findTestsIn(file));
            } else if (file.getName().endsWith(".html")) {
                tests.add(file);
            }
        }

        return tests;
    }

    public void synchronise(String source, String target) {
        synchronise(new File(source), new File(target));
    }

    public void synchronise(File source, File target) {
        Collection<File> resourcesInSource = listFiles(source, ResourcesFilter.INSTANCE, ResourcesFilter.INSTANCE);
        for (File fileInSource : resourcesInSource) {
            File relativeFile = relativeFile(source, fileInSource);
            File fileInTarget = new File(target, relativeFile.getPath());
            if (shouldCopy(fileInSource, fileInTarget)) {
                System.out.println("copying to " + fileInTarget);
                copier.copy(fileInSource, fileInTarget);
            }
        }
    }

    private boolean shouldCopy(File fileInSource, File fileInTarget) {
        return !fileInTarget.exists()
                || isFileNewer(fileInSource, fileInTarget)
                || fileInSource.length() != fileInTarget.length();
    }

    @Override
    public void copy(File source, File target) {
        try {
            copyFile(source, target);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static class ResourcesFilter implements IOFileFilter {
        public static ResourcesFilter INSTANCE = new ResourcesFilter();

        public boolean accept(File file) {
            return !file.getName().matches("(\\.svn)|(.*html)|(.*java)");
        }

        public boolean accept(File dir, String name) {
            return true;
        }
    }

}
